package com.zoke.daycarpool.view;

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.zoke.daycarpool.R;

public class PullToRefreshLayout extends RelativeLayout {
	public static final String TAG = "PullToRefreshLayout";
	public static final int INIT = 0;
	public static final int RELEASE_TO_REFRESH = 1;
	public static final int REFRESHING = 2;
	public static final int RELEASE_TO_LOAD = 3;
	public static final int LOADING = 4;
	public static final int DONE = 5;
	private int state = INIT;
	private OnRefreshListener mListener;
	public static final int SUCCEED = 0;
	public static final int FAIL = 1;
	private float downY, lastY;

	public float pullDownY = 0;
	private float pullUpY = 0;

	private float refreshDist = 200;
	private float loadmoreDist = 200;

	private MyTimer timer;
	public float MOVE_SPEED = 8;
	private boolean isLayout = false;
	private boolean isTouch = false;
	private float radio = 2;

	private View loadmoreView;
	private View refreshView;

	private ImageView mRefreshIv;
	private ImageView mLoadmoreIv;

	private AnimationDrawable refreshAnimaDrawable;
	private AnimationDrawable moreAnimaDrawable;

	private View pullableView;
	private int mEvents;
	private boolean canPullDown = true;
	private boolean canPullUp = true;

	Handler updateHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			MOVE_SPEED = (float) (8 + 5 * Math.tan(Math.PI / 2
					/ getMeasuredHeight() * (pullDownY + Math.abs(pullUpY))));
			if (!isTouch) {
				if (state == REFRESHING && pullDownY <= refreshDist) {
					pullDownY = refreshDist;
					timer.cancel();
				} else if (state == LOADING && -pullUpY <= loadmoreDist) {
					pullUpY = -loadmoreDist;
					timer.cancel();
				}

			}
			if (pullDownY > 0)
				pullDownY -= MOVE_SPEED;
			else if (pullUpY < 0)
				pullUpY += MOVE_SPEED;
			if (pullDownY < 0) {
				pullDownY = 0;
				// 停止动画
				stopRefreshAnima();
				if (state != REFRESHING && state != LOADING)
					changeState(INIT);
				timer.cancel();
				requestLayout();
			}
			if (pullUpY > 0) {
				pullUpY = 0;
				// 停止动画
				stopMoreAnima();
				if (state != REFRESHING && state != LOADING)
					changeState(INIT);
				timer.cancel();
			}
			requestLayout();
		}

	};

	public void setOnRefreshListener(OnRefreshListener listener) {
		mListener = listener;
	}

	public PullToRefreshLayout(Context context) {
		super(context);
		initView(context);
	}

	public PullToRefreshLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context);
	}

	public PullToRefreshLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView(context);
	}

	private void initView(Context context) {
		timer = new MyTimer(updateHandler);
	}

	private void hide() {
		timer.schedule(5);
	}

	/** 下拉刷新结束 **/
	public void refreshFinish() {
		stopRefreshAnima();
		changeState(DONE);
		hide();
	}

	/** 下拉刷新结束 **/
	public void loadmoreFinish() {
		stopMoreAnima();
		changeState(DONE);
		hide();
	}

	/** 改变状态 **/
	private void changeState(int to) {
		state = to;
		switch (state) {
		case INIT:
			// 初始化－－
			break;
		case RELEASE_TO_REFRESH:
			break;
		case REFRESHING:
			// 正在刷新中
			startRefreshAnima();
			break;
		case RELEASE_TO_LOAD:
			break;
		case LOADING:
			// 正在加载更多
			startMoreAnima();
			break;
		case DONE:
			break;
		}
	}

	private void releasePull() {
		canPullDown = true;
		canPullUp = true;
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		switch (ev.getActionMasked()) {
		case MotionEvent.ACTION_DOWN:
			downY = ev.getY();
			lastY = downY;
			timer.cancel();
			mEvents = 0;
			releasePull();
			break;
		case MotionEvent.ACTION_POINTER_DOWN:
		case MotionEvent.ACTION_POINTER_UP:
			mEvents = -1;
			break;
		case MotionEvent.ACTION_MOVE:
			if (mEvents == 0) {
				if (pullDownY > 0
						|| (((Pullable) pullableView).canPullDown()
								&& canPullDown && state != LOADING)) {
					pullDownY = pullDownY + (ev.getY() - lastY) / radio;
					if (pullDownY < 0) {
						pullDownY = 0;
						canPullDown = false;
						canPullUp = true;
					}
					if (pullDownY > getMeasuredHeight())
						pullDownY = getMeasuredHeight();
					if (state == REFRESHING) {
						isTouch = true;
					}
				} else if (pullUpY < 0
						|| (((Pullable) pullableView).canPullUp() && canPullUp && state != REFRESHING)) {
					pullUpY = pullUpY + (ev.getY() - lastY) / radio;
					if (pullUpY > 0) {
						pullUpY = 0;
						canPullDown = true;
						canPullUp = false;
					}
					if (pullUpY < -getMeasuredHeight())
						pullUpY = -getMeasuredHeight();
					if (state == LOADING) {
						isTouch = true;
					}
				} else
					releasePull();
			} else
				mEvents = 0;
			lastY = ev.getY();
			radio = (float) (2 + 2 * Math.tan(Math.PI / 2 / getMeasuredHeight()
					* (pullDownY + Math.abs(pullUpY))));
			requestLayout();
			if (pullDownY > 0) {
				if (pullDownY <= refreshDist
						&& (state == RELEASE_TO_REFRESH || state == DONE)) {
					changeState(INIT);
				}
				if (pullDownY >= refreshDist && state == INIT) {
					changeState(RELEASE_TO_REFRESH);
				}
			} else if (pullUpY < 0) {
				if (-pullUpY <= loadmoreDist
						&& (state == RELEASE_TO_LOAD || state == DONE)) {
					changeState(INIT);
				}
				if (-pullUpY >= loadmoreDist && state == INIT) {
					changeState(RELEASE_TO_LOAD);
				}

			}
			if ((pullDownY + Math.abs(pullUpY)) > 8) {
				ev.setAction(MotionEvent.ACTION_CANCEL);
			}
			break;
		case MotionEvent.ACTION_UP:
			if (pullDownY > refreshDist || -pullUpY > loadmoreDist)
				isTouch = false;
			if (state == RELEASE_TO_REFRESH) {
				changeState(REFRESHING);
				if (mListener != null)
					mListener.onRefresh(this);
			} else if (state == RELEASE_TO_LOAD) {
				changeState(LOADING);
				if (mListener != null)
					mListener.onLoadMore(this);
			}
			hide();
		default:
			break;
		}
		super.dispatchTouchEvent(ev);
		return true;
	}

	/** 开始播放下拉刷新动画 **/
	private void startRefreshAnima() {
		if (refreshAnimaDrawable == null)
			return;
		refreshAnimaDrawable.start();
	}

	/** 停止播放下拉刷新动画 **/
	private void stopRefreshAnima() {
		if (refreshAnimaDrawable == null)
			return;
		refreshAnimaDrawable.stop();
	}

	/** 开始加载更多动画 **/
	private void startMoreAnima() {
		if (moreAnimaDrawable == null)
			return;
		moreAnimaDrawable.start();
	}

	/** 停止加载更多动画 **/
	private void stopMoreAnima() {
		if (moreAnimaDrawable == null)
			return;
		moreAnimaDrawable.stop();
	}

	// 初始化控件
	private void initView() {
		// 加载动画View
		mRefreshIv = (ImageView) refreshView.findViewById(R.id.refreshIv);
		mLoadmoreIv = (ImageView) loadmoreView.findViewById(R.id.loadmoreIv);
		// 初始化贞动画
		refreshAnimaDrawable = (AnimationDrawable) mRefreshIv.getDrawable();
		moreAnimaDrawable = (AnimationDrawable) mLoadmoreIv.getDrawable();

	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		if (!isLayout) {
			refreshView = getChildAt(0);
			pullableView = getChildAt(1);
			loadmoreView = getChildAt(2);
			isLayout = true;
			initView();
			refreshDist = ((ViewGroup) refreshView).getChildAt(0)
					.getMeasuredHeight();
			loadmoreDist = ((ViewGroup) loadmoreView).getChildAt(0)
					.getMeasuredHeight();
		}
		refreshView.layout(0,
				(int) (pullDownY + pullUpY) - refreshView.getMeasuredHeight(),
				refreshView.getMeasuredWidth(), (int) (pullDownY + pullUpY));
		pullableView.layout(0, (int) (pullDownY + pullUpY),
				pullableView.getMeasuredWidth(), (int) (pullDownY + pullUpY)
						+ pullableView.getMeasuredHeight());
		loadmoreView.layout(0,
				(int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight(),
				loadmoreView.getMeasuredWidth(),
				(int) (pullDownY + pullUpY) + pullableView.getMeasuredHeight()
						+ loadmoreView.getMeasuredHeight());
	}

	class MyTimer {
		private Handler handler;
		private Timer timer;
		private MyTask mTask;

		public MyTimer(Handler handler) {
			this.handler = handler;
			timer = new Timer();
		}

		public void schedule(long period) {
			if (mTask != null) {
				mTask.cancel();
				mTask = null;
			}
			mTask = new MyTask(handler);
			timer.schedule(mTask, 0, period);
		}

		public void cancel() {
			if (mTask != null) {
				mTask.cancel();
				mTask = null;
			}
		}

		class MyTask extends TimerTask {
			private Handler handler;

			public MyTask(Handler handler) {
				this.handler = handler;
			}

			@Override
			public void run() {
				handler.obtainMessage().sendToTarget();
			}

		}
	}

	public interface OnRefreshListener {
		void onRefresh(PullToRefreshLayout pullToRefreshLayout);

		void onLoadMore(PullToRefreshLayout pullToRefreshLayout);
	}

}
